package com.dhecp.core.utils.dingtalk;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dhecp.common.config.Global;
import com.dhecp.common.utils.CacheUtils;
import com.dhecp.common.utils.StringUtils;
import com.dhecp.common.utils.TypeUtils;
import com.dhecp.core.utils.qywx.QyWxResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @ClassName 钉钉工具类
 * @Description TODO
 * @Author alula
 * @Date 2022-03-04 16:39
 */
public class DingTalkUtils {
    private static final Logger logger = LoggerFactory.getLogger(DingTalkUtils.class);

    //钉钉企业ID
    public static String CORPID = Global.getConfig("dt.corpid");
    //钉钉H5应用ID：AGENTID
    public static String AGENTID = Global.getConfig("dt.agentid");
    //钉钉H5应用KEY
    public static String H5APPKEY = Global.getConfig("dt.appkey");
    //钉钉H5应用secret
    public static String H5APPSECERT = Global.getConfig("dt.appsecret");
    //钉钉H5应用缓存KEY
    public static String H5CACHEKEY = "H5ApplyCache";

    /**
     * 获取钉钉企业ID
     * @return
     */
    public static  String getCorpId(){
        return CORPID;
    }

    /**
     * 获取钉钉H5应用ID
     * @return
     */
    public static String getAgentId(){
        return AGENTID;
    }

    /**
     * 获到钉钉token
     * @param appKey
     * @param appSecret
     * @param cacheKey
     * @return
     */
    public static String getToken(String appKey, String appSecret, String cacheKey) {
        String token = "";
        String dtTokenExpiresKey = "DtTokenExpires_" +cacheKey;
        String dtTokenKey = "DtToken_"+cacheKey;
        if(CacheUtils.get(dtTokenExpiresKey) == null || CacheUtils.get(dtTokenExpiresKey).equals("") || new Date().after((Date) CacheUtils.get(dtTokenExpiresKey))) {//缓存中不存在凭证有效期或失效{
            String requestUrl = DtApiUrls.ACCESS_TOKEN_URL.replace("APPKEY", appKey).replace("APPSECRET", appSecret);
            JSONObject jsonObject = DtHttpUtils.sendGet(requestUrl);
            String errCode = jsonObject.getString("errcode");
            if (errCode.equals("0")) {
                token = jsonObject.getString("access_token");
                CacheUtils.put(dtTokenKey,token);//获取最新凭证
                CacheUtils.put(dtTokenExpiresKey,new Date(System.currentTimeMillis() + 60*60*1000));//设置凭证有效期为当前时间+1小时
            }else{
                String errMsg = jsonObject.getString("errmsg");
                logger.error("【钉钉】", "获取access_token失败，errCode：{}，errMsg：{}", new Object[]{errCode,errMsg});
            }
        }else {
            token = CacheUtils.get(dtTokenKey).toString();
        }
        return  token;
    }

    /**
     * 更新钉钉token
     * @param appKey
     * @param appSecret
     * @param cacheKey
     * @return
     */
    public static String updateToken(String appKey, String appSecret, String cacheKey) {
        String token = "";
        String dtTokenExpiresKey = "DtTokenExpires_" +cacheKey;
        String dtTokenKey = "DtToken_"+cacheKey;
        String requestUrl = DtApiUrls.ACCESS_TOKEN_URL.replace("APPKEY", appKey).replace("APPSECRET", appSecret);
        JSONObject jsonObject = DtHttpUtils.sendGet(requestUrl);
        String errCode = jsonObject.getString("errcode");
        if (errCode.equals("0")) {
            token = jsonObject.getString("access_token");
            CacheUtils.put(dtTokenKey,token);//获取最新凭证
            CacheUtils.put(dtTokenExpiresKey,new Date(System.currentTimeMillis() + 60*60*1000));//设置凭证有效期为当前时间+1小时
        }else{
            String errMsg = jsonObject.getString("errmsg");
            logger.error("【钉钉】", "更新access_token失败，errCode：{}，errMsg：{}", new Object[]{errCode,errMsg});
        }
        return  token;
    }


    /** 获到钉钉jsapi_ticket
     * @param token
     * @return
     */
    public static String getTicket(String token) {
        String ticket = "";
        if(CacheUtils.get("DtTicketExpires") == null || CacheUtils.get("DtTicketExpires").equals("") || new Date().after((Date) CacheUtils.get("DtTicketExpires"))) {//缓存中不存在凭证有效期或失效{
            // 调用接口获取替换ACCESS_TOKEN
            String requestUrl = DtApiUrls.JSAPI_TICKET_URL.replace("ACCESS_TOKEN", token);
            JSONObject jsonObject = DtHttpUtils.sendGet(requestUrl);
            String errCode = jsonObject.getString("errcode");
            if(errCode.equals("0")){
                ticket = jsonObject.getString("ticket");
                CacheUtils.put("DtTicket",ticket);//获取最新凭证
                CacheUtils.put("DtTicketExpires",new Date(System.currentTimeMillis() + 60*60*1000));//设置凭证有效期为当前时间+1小时
            }else{
                String errMsg = jsonObject.getString("errmsg");
                logger.error("【钉钉】", "获取ticket失败，errCode：{}，errMsg：{}", new Object[]{errCode,errMsg});
            }
        }else {
            ticket = CacheUtils.get("DtTicket").toString();
        }
        return  ticket;
    }

    /**
     * 更新钉钉jsapi_ticket
     * @param token
     * @return
     */
    public static String updateTicket(String token) {
        // 调用接口获取替换ACCESS_TOKEN
        String ticket = "";
        String requestUrl = DtApiUrls.JSAPI_TICKET_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendGet(requestUrl);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            ticket = jsonObject.getString("ticket");
            CacheUtils.put("DtTicket",ticket);//获取最新凭证
            CacheUtils.put("DtTicketExpires",new Date(System.currentTimeMillis() + 60*60*1000));//设置凭证有效期为当前时间+1小时
        }else{
            String errMsg = jsonObject.getString("errmsg");
            logger.error("【钉钉】", "更新ticket失败，errCode：{}，errMsg：{}", new Object[]{errCode,errMsg});
        }
        return  ticket;
    }

    /**
     *
     * @param userList 接收者的userid列表
     * @param deptList 接收者的部门id列表
     * @param toAllUser 是否发送给企业全部用户。
     * @param content 发送内容
     * @return
     */
    public static DtResponse sendTextMsg(List<String> userList, List<String> deptList, boolean toAllUser, String content){
        DtResponse dtResponse = new DtResponse();
        if ((userList == null ||  userList.size() == 0) && (deptList == null || deptList.size() == 0) && toAllUser == false){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("当toAllUser设置为false时，接收消息的成员列表[userList、deptList]两种类型成员不能同时为空，必须要有一种类型有值!");
            return dtResponse;
        }
        if (StringUtils.isEmpty(content)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】发送消息[content]内容参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("agent_id",AGENTID);//企业应用的id，整型
        params.put("to_all_user",toAllUser);//是否发送给企业全部用户，默认为false
        if (userList != null && userList.size() > 0){//用户
            params.put("userid_list", StringUtils.join(userList,","));
        }
        if (deptList != null && deptList.size() > 0){//部门
            params.put("dept_id_list", StringUtils.join(deptList,","));
        }
        Map<String, Object> sendContent = new HashMap<String, Object>();
        sendContent.put("content", content);
        Map<String, Object> sendMsg = new HashMap<String, Object>();
        sendMsg.put("msgtype", "text");
        sendMsg.put("text", sendContent);
        params.put("msg", sendMsg);
        String postStr = JSONObject.toJSONString(params);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.MESSAGE_SEND_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】文本消息发送成功！");
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】文本消息发送失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 发送卡片形式消息
     * @param userList 接收者的userid列表
     * @param deptList 接收者的部门id列表
     * @param toAllUser 是否发送给企业全部用户。
     * @param title 消息标题
     * @param content 消息内容 (支持markdown格式的正文内容)
     * @param url 消息点击链接地址
     * @param btnTxt 按钮文字。 默认为“查看详情”， 不超过20个文字
     * @return
     */
    public static DtResponse sendActionCardMsg(List<String> userList, List<String> deptList, boolean toAllUser, String title, String content, String url,  String btnTxt){
        DtResponse dtResponse = new DtResponse();
        if ((userList == null ||  userList.size() == 0) && (deptList == null || deptList.size() == 0) && toAllUser == false){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("当toAllUser设置为false时，接收消息的成员列表[userList、deptList]两种类型成员不能同时为空，必须要有一种类型有值!");
            return dtResponse;
        }
        if (StringUtils.isEmpty(content)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】发送消息[content]内容参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("agent_id",AGENTID);//企业应用的id，整型
        params.put("to_all_user",toAllUser);//是否发送给企业全部用户，默认为false
        if (userList != null && userList.size() > 0){//用户
            params.put("userid_list", StringUtils.join(userList,","));
        }
        if (deptList != null && deptList.size() > 0){//部门
            params.put("dept_id_list", StringUtils.join(deptList,","));
        }
        Map<String, Object> sendContent = new HashMap<String, Object>();
        sendContent.put("title", title);
        sendContent.put("markdown", content);
        sendContent.put("single_title", btnTxt);
        sendContent.put("single_url", url);
        Map<String, Object> sendMsg = new HashMap<String, Object>();
        sendMsg.put("msgtype", "action_card");
        sendMsg.put("action_card", sendContent);
        params.put("msg", sendMsg);
        String postStr = JSONObject.toJSONString(params);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.MESSAGE_SEND_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】卡片消息发送成功！");
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】卡片消息发送失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 发送MarkDown形式消息
     * @param userList 接收者的userid列表
     * @param deptList 接收者的部门id列表
     * @param toAllUser 是否发送给企业全部用户。
     * @param title 消息标题
     * @param content 消息内容(markdown格式的正文内容)
     * @return
     */
    public static DtResponse sendMarkDownMsg(List<String> userList, List<String> deptList, boolean toAllUser, String title, String content){
        DtResponse dtResponse = new DtResponse();
        if ((userList == null ||  userList.size() == 0) && (deptList == null || deptList.size() == 0) && toAllUser == false){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("当toAllUser设置为false时，接收消息的成员列表[userList、deptList]两种类型成员不能同时为空，必须要有一种类型有值!");
            return dtResponse;
        }
        if (StringUtils.isEmpty(content)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】发送消息[content]内容参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("agent_id",AGENTID);//企业应用的id，整型
        params.put("to_all_user",toAllUser);//是否发送给企业全部用户，默认为false
        if (userList != null && userList.size() > 0){//用户
            params.put("userid_list", StringUtils.join(userList,","));
        }
        if (deptList != null && deptList.size() > 0){//部门
            params.put("dept_id_list", StringUtils.join(deptList,","));
        }
        Map<String, Object> sendContent = new HashMap<String, Object>();
        sendContent.put("title", title);
        sendContent.put("text", content);
        Map<String, Object> sendMsg = new HashMap<String, Object>();
        sendMsg.put("msgtype", "markdown");
        sendMsg.put("markdown", sendContent);
        params.put("msg", sendMsg);
        String postStr = JSONObject.toJSONString(params);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.MESSAGE_SEND_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】markdown消息发送成功！");
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】markdown消息发送失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 获取打卡记录详情
     * @param startTime
     * @param endTime
     * @param userList
     * @return
     */
    public static DtResponse getAttendanceData(String startTime, String endTime, List<String> userList){
        DtResponse dtResponse = new DtResponse();
        if (StringUtils.isEmpty(startTime)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】打卡开始时间参数[startTime]不能为空！");
            return dtResponse;
        }
        if (StringUtils.isEmpty(endTime)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】打卡结束时间参数[endTime]不能为空！");
            return dtResponse;
        }
        if (userList == null || userList.size() == 0){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】打卡用户列表参数[userList]不能为零！");
            return dtResponse;
        }
        Map<String, Object> sendParams = new HashMap<String, Object>();
        sendParams.put("isI18n", false);
        sendParams.put("checkDateFrom", startTime);
        sendParams.put("checkDateTo", endTime);
        sendParams.put("userIds", userList);
        String postStr = JSONObject.toJSONString(sendParams);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.ATTENDANCE_GET_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】打卡数据获取成功！");
            Object checkData = jsonObject.get("recordresult");
            dtResponse.setData(checkData);
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】打卡数据获取失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 创建钉钉用户
     * @param model 用户对象实体
     * @return
     */
    public static DtResponse userCreate(UserEntity model){
        DtResponse dtResponse = new DtResponse();
        if (model == null){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】参数[model]对象不能为空！");
            return dtResponse;
        }
        if (StringUtils.isEmpty(model.getUserName())){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】userName参数不能为空！");
            return dtResponse;
        }
        if (StringUtils.isEmpty(model.getDepIdList())){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】depIdList参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> userParams = new HashMap<String, Object>();
        userParams.put("name",model.getUserName());
        if (!StringUtils.isEmpty(model.getMobile())) {
            userParams.put("mobile", model.getMobile());
            userParams.put("hide_mobile",model.getHideMobile());
        }
        if (!StringUtils.isEmpty(model.getTelephone())) {
            userParams.put("telephone", model.getTelephone());
        }
        if (!StringUtils.isEmpty(model.getJobNumber())) {
            userParams.put("job_number", model.getJobNumber());
        }
        if (!StringUtils.isEmpty(model.getTitle())) {
            userParams.put("title", model.getTitle());
        }
        if (!StringUtils.isEmpty(model.getEmail())) {
            userParams.put("email", model.getEmail());
        }
        if (!StringUtils.isEmpty(model.getOrgEmail())) {
           userParams.put("org_email", model.getOrgEmail());
        }
        if (!StringUtils.isEmpty(model.getWorkPlace())) {
            userParams.put("work_place", model.getWorkPlace());
        }
        if (!StringUtils.isEmpty(model.getRemark())) {
            userParams.put("remark", model.getRemark());
        }
        if (!StringUtils.isEmpty(model.getDepIdList())){
            userParams.put("dept_id_list", model.getDepIdList());
        }
        userParams.put("senior_mode", model.getSeniorMode());
        if (model.getHiredDate() !=0l) {
            userParams.put("hired_date", model.getHiredDate());
        }
        //if (!StringUtils.isEmpty(model.getManagerUserId())) {
           //userParams.put("manager_userid", model.getManagerUserId());
        //}
        if (!StringUtils.isEmpty(model.getNickname())) {
            userParams.put("nickname", model.getNickname());
        }
        String postStr = JSONObject.toJSONString(userParams, SerializerFeature.WriteNullStringAsEmpty);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.USER_CREATE_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】用户信息同步创建成功！");
            JSONObject dataObject = jsonObject.getJSONObject("result");
            dtResponse.setData(dataObject);
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】用户信息同步创建失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 更新钉钉用户
     * @param model 用户对象实体
     * @return
     */
    public static DtResponse userUpdate(UserEntity model){
        DtResponse dtResponse = new DtResponse();
        if (model == null){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】参数[model]对象不能为空！");
            return dtResponse;
        }
        if (StringUtils.isEmpty(model.getUserId())){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】userId参数不能为空！");
            return dtResponse;
        }
        if (StringUtils.isEmpty(model.getUserName())){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】userName参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> userParams = new HashMap<String, Object>();
        userParams.put("userid",model.getUserId());
        userParams.put("name",model.getUserName());
        if (!StringUtils.isEmpty(model.getMobile())) {
            userParams.put("mobile", model.getMobile());
        }
        userParams.put("hide_mobile",model.getHideMobile());
        if (!StringUtils.isEmpty(model.getTelephone())) {
            userParams.put("telephone", model.getTelephone());
        }
        if (!StringUtils.isEmpty(model.getJobNumber())) {
            userParams.put("job_number", model.getJobNumber());
        }
        if (!StringUtils.isEmpty(model.getTitle())) {
            userParams.put("title", model.getTitle());
        }
        if (!StringUtils.isEmpty(model.getEmail())) {
            userParams.put("email", model.getEmail());
        }
        if (!StringUtils.isEmpty(model.getOrgEmail())) {
            userParams.put("org_email", model.getOrgEmail());
        }
        if (!StringUtils.isEmpty(model.getWorkPlace())) {
            userParams.put("work_place", model.getWorkPlace());
        }
        if (!StringUtils.isEmpty(model.getRemark())) {
            userParams.put("remark", model.getRemark());
        }
        //userParams.put("dept_id_list",model.getDepIdList().split(","));
        userParams.put("senior_mode", model.getSeniorMode());
        if (model.getHiredDate() !=0l) {
            userParams.put("hired_date", model.getHiredDate());
        }
        //if (!StringUtils.isEmpty(model.getManagerUserId())) {
            //userParams.put("manager_userid", model.getManagerUserId());
        //}
        if (!StringUtils.isEmpty(model.getNickname())) {
            userParams.put("nickname", model.getNickname());
        }
        userParams.put("language", model.getLanguage());
        String postStr = JSONObject.toJSONString(userParams, SerializerFeature.WriteNullStringAsEmpty);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.USER_UPDATE_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】用户信息同步更新成功！");
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】用户信息同步更新失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }

    /**
     * 删除钉钉用户
     * @param userId
     * @return
     */
    public static DtResponse userDelete(String userId){
        DtResponse dtResponse = new DtResponse();
        if (StringUtils.isEmpty(userId)){
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg("【钉钉】userId参数不能为空！");
            return dtResponse;
        }
        Map<String, Object> userParams = new HashMap<String, Object>();
        userParams.put("userid",userId);
        String postStr = JSONObject.toJSONString(userParams);
        String token = getToken(H5APPKEY,H5APPSECERT, H5CACHEKEY);
        //发起请求
        String requestUrl = DtApiUrls.USER_DELETE_URL.replace("ACCESS_TOKEN", token);
        JSONObject jsonObject = DtHttpUtils.sendPost(requestUrl, postStr);
        String errCode = jsonObject.getString("errcode");
        if(errCode.equals("0")){
            dtResponse.setErrCode(0);
            dtResponse.setErrMsg("【钉钉】用户信息同步删除成功！");
        }else {
            String errMsg = jsonObject.getString("errmsg");
            dtResponse.setErrCode(500);
            dtResponse.setErrMsg(String.format("【钉钉】用户信息同步删除失败，具体错误为：errCode：%s，errMsg：%s", errCode,errMsg));
        }
        return  dtResponse;
    }
}
